#============================================================
#    Data Steward
#============================================================
# - datetime: 2023-01-08 14:38:33
#============================================================
class_name DataSteward
extends Node
 

## 新增数据
signal newly_added_data(id: String, data: Dictionary)
## 移除数据
signal removed_data(id: String, data: Dictionary)
## 数据发生改变
signal property_changed(id: String, previous: Dictionary, current: Dictionary)


## 以这个 key 作为主键记录数据，根据这个 key 的值可以直接获取到这个数据
@export
var id_key : String = ""


var _id_to_data_map : Dictionary = {}


#============================================================
#  SetGet
#============================================================
func _get_id(data: Dictionary):
	return data.get(id_key)

## 获取所有数据
func get_all_data() -> Array[Dictionary]:
	return _id_to_data_map.values()

## 是否有这个ID的数据
func has_data(id: String) -> bool:
	return _id_to_data_map.has(id)

## 获取这个 ID 的数据
func get_data(id: String) -> Dictionary:
	return _id_to_data_map.get(id, {})


## 设置数据
func set_data(data: Dictionary):
	if data.has(id_key):
		var id = data.get(id_key)
		var previous = _id_to_data_map.get(id, {}) as Dictionary
		if _id_to_data_map.has(id):
			_id_to_data_map[id] = data
			self.property_changed.emit(id, previous, data)
		else:
			_id_to_data_map[id] = data
			self.newly_added_data.emit(id, data)
	else:
		printerr("添加的数据没有这个 ID 键！")


## 移除这个ID的数据
func remove_data(id: String) -> bool:
	if _id_to_data_map.has(id):
		var data = _id_to_data_map[id]
		_id_to_data_map.erase(id)
		self.removed_data.emit(id, data)
		return true
	return false


## 添加数据
func add_data(data: Dictionary, keys: PackedStringArray = PackedStringArray()):
	data = data.duplicate(true)
	var id = _get_id(data)
	if has_data(id):
		if keys.is_empty():
			keys = data.keys()
		var value
		alter_data(id, data, func(key, previous, current):
			value = data.get(key)
			if (key in keys 
				and (value is float 
					or value is int
				)
			):
				return previous.get(key) + data.get(key)
		)
	else:
		set_data(data)


## 减去数据
##[br]
##[br][code]data[/code]  减去的数据，如果没有设置 [member stackable_keys] 参数的值，则
##不会有任何改变
func sub_data(data: Dictionary, keys: PackedStringArray = PackedStringArray()):
	data = data.duplicate(true)
	for key in data:
		if data[key] is float or data[key] is int:
			data[key] = -data[key]
	add_data(data, keys)


##  修改数据
##[br]
##[br][code]id[/code]  修改的数据的ID
##[br][code]new_data[/code]  修改的新的数据
##[br][code]callable[/code]  修改数据时的回调方法，这个方法需要接收，数据的 key、旧的数据
##([Dictionary]) 和这次新的数据 ([Dictionary]) 3 个参数，并返回修改后的数据
func alter_data(id: String, new_data: Dictionary, callable: Callable):
	if has_data(id):
		var data = get_data(id)
		var v
		for key in new_data:
			v = callable.call(key, data, new_data)
			if v:
				new_data[key] = v
		new_data.merge(data)
	set_data(new_data)


##  过滤数据
##[br]
##[br][code]condition[/code]  过滤条件方法，这个方法需要接收一个 [Dictionary] 类型的参数
##并返回 bool 类型的数据
##[br][code]return[/code]  返回过滤后的数据列表
func filter(condition: Callable) -> Array[Dictionary]:
	var list = []
	for data in _id_to_data_map.values():
		if condition.call(data):
			list.append(data)
	return list


